#-*- coding: utf-8 -*-

import sys, os
import socket
import thread
import threading
import time
import traceback
import struct
from collections import deque

g_debug = True

g_exit = False
message = deque()
filedata = deque()
filelist = deque()
sendfile = {}
g_socket = None
g_status = False
def datahandler(s):
        while True:
                try:
                        if g_exit:
                                break
                        if not g_status:
                                data = s.recv(1024)
                                if g_exit:
                                        break
                                if data == "":
                                        #connection lost
                                        s = connectSrver()
                                message.append(data)
                                
                        time.sleep(0.1)
                except:
                        if g_debug:
                              traceback.print_exc()
        print("Thread Exited")

def msghandler():
        while True:
                try:
                        if g_exit:
                                break
                        if len(message) > 0:
                                data = message.pop()
                                if data:
                                        if data.find(":") >= 0:
                                                content = data.split(":", 1)[1];
                                                if content.startswith("file"):
                                                        alias = data.split(":", 1)[0]
                                                        data = content

                                                        #print(data);
                                                        global g_status
                                                        g_status = True
                                                        try:
                                                                #fileinfo_size = struct.calcsize("128sld")
                                                                #print(fileinfo_size)
                                                                #data = data.split(" ", 1)[1][:fileinfo_size]
                                                                #print(len(data))
                                                                #filepath, filesize, status = struct.unpack("128sld", data)
                                                                data = data.split(" ", 1)[1]
                                                                print(data)
                                                                status, index, filesize, filepath = data.split(" ")
                                                                status = int(status)
                                                                filesize = int(filesize)
                                                                print "size {0}, ststus {1}, file{2}".format( filesize, status, filepath)

                                                                if status == 0:
                                                                        print("data pushed")
                                                                        data += " " + alias
                                                                        print(data)
                                                                        filelist.append(data)
                                                                if status == 1:
                                                                        #fileinfo_size = struct.calcsize("128sld")
                                                                        #fhead = struct.pack("128sld", filepath, filesize, 2)
                                                                        #g_socket.send("file " + fhead)
                                                                        #print "Client filepath: {0}".format(filepath)
                                                                        g_socket.send("file 2 " + index)
                                                                        print "Client filepath: {0}".format(filepath)
                                                                elif status == 3:
                                                                        fp = open(filepath, "rb")
                                                                        addalias = ""
                                                                        while True:
                                                                                data = fp.read(1019)
                                                                                if not data:
                                                                                        print "{0} file send fininshed.".format(filepath)
                                                                                        break
                                                                                print("send:" + data)
                                                                                g_socket.send("data " + data)
                                                                                while True:
                                                                                        data = g_socket.recv(1024)
                                                                                        print(data)
                                                                                        if data.startswith("data "):
                                                                                                break
                                                                                        elif data.startswith("disconnected"):
                                                                                                addalias = data.split(" ")[1]
                                                                                                if alias == addalias:
                                                                                                        break
                                                                                                
                                                                                if alias == addalias:
                                                                                        print("Error");
                                                                                        break
                                                                        fp.close()
                                                                        #del sendfile[fn]
                                                                elif status == 2:
                                                                        #fileinfo_size = struct.calcsize("128sld")
                                                                        #fhead = struct.pack("128sld", filepath, filesize, 3)
                                                                        #g_socket.send("file " + fhead)
                                                                        #print "Client filepath: {0}".format(filepath)
                                                                        g_socket.send("file 3 " + index)
                                                                        print "Client filepath: {0}".format(filepath)
                                                                        
                                                                        recv_size = 0
                                                                        fn = os.path.basename(filepath).strip("\00")
                                                                        new_filepath = os.path.join("./", "new_" + fn)
                                                                        print("New file: " + new_filepath)
                                                                        fp = open(new_filepath, "wb")
                                                                        try:
                                                                                print("start receiving")
                                                                                while not recv_size == filesize:
                                                                                        size = 0
                                                                                        if filesize - recv_size > 1024:
                                                                                                data = g_socket.recv(1024)
                                                                                                size = recv_size + len(data) - 5
                                                                                        else:
                                                                                                data = g_socket.recv(filesize- recv_size + 5)
                                                                                                size = filesize
                                                                                        print(data)
                                                                                        print(len(data), size)
                                                                                        if data.startswith("data "):
                                                                                                recv_size = size
                                                                                                data = data.split(" ", 1)[1]
                                                                                                fp.write(data)
                                                                                                g_socket.send("data ")
                                                                                        elif data.startswith("disconnected"):
                                                                                                addalias = data.split(" ")[1]
                                                                                                if alias == addalias:
                                                                                                        break
                                                                                        print(recv_size, filesize)
                                                                                print("end receving")
                                                                        except:
                                                                                if g_debug:
                                                                                        traceback.print_exc()
                                                                        fp.close()
                                                        except:
                                                                if g_debug:
                                                                        traceback.print_exc()
                                                        g_status = False
                                                else:
                                                        print(data)
                                        else:
                                                #server message
                                                print(data)
                                
                        time.sleep(0.1)
                except:
                        if g_debug:
                                traceback.print_exc()
        print("msg Thread Exited")


def connectSrver():
        global g_socket
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        while True:
                try:
                        if g_exit:
                                break
                        s.connect((socket.gethostname(), 8000))
                        print("connected!")
                        g_socket = s
                        break
                except:
                        if g_debug:
                                traceback.print_exc()
                        print("connection failed, reconnecting...")

        return s

def main():
        connectSrver()

        dt = threading.Thread(target=datahandler, args=(g_socket,))
        dt.start()
        mt = threading.Thread(target=msghandler, args=())
        mt.start()
        try:
                while True:
                        content = raw_input("")
                        #content = ""
                        if content == "exit":
                                break
                        #do something else

                        elif content == "":
                                pass
                        elif content.startswith("#"):
                                try:
                                        filepath = content.split("#", 1)[1]
                                        print(filepath)

                                        if os.path.isfile(filepath):
                                                #fileinfo_size = struct.calcsize("128sld")
                                                #fhead = struct.pack("128sld", os.path.basename(filepath), os.stat(filepath).st_size, 0)
                                                #g_socket.send("file " + fhead)
                                                #print "Client filepath: {0}".format(filepath)
                                                #sendfile[os.path.basename(filepath)] = filepath
                                                
                                                print "Client filepath: {0}".format(filepath)
                                                g_socket.send("file 0 " + str(os.stat(filepath).st_size) + " " + filepath)
                                except:
                                        if g_debug:
                                                traceback.print_exc()
                        elif content.startswith("file"):
                                try:
                                        data = filelist.pop()

                                        if data:
                                                #filepath, filesize, status = struct.unpack("128sld", data)
                                                #fileinfo_size = struct.calcsize("128sld")
                                                #fhead = struct.pack("128sld", filepath, filesize, 1)
                                                #g_socket.send("file " + fhead)
                                                #print "Client filepath: {0}".format(filepath)

                                                print data
                                                status, index, filesize, filepath, alias= data.split(" ")
                                                print "Client filepath: {0}".format(filepath)
                                                g_socket.send("file 1 " + index + " " + alias)
                                                

                                except:
                                        if g_debug:
                                                traceback.print_exc()
                                        
                        else:
                                g_socket.send(content)

                        time.sleep(0.5)
        except:
                if g_debug:
                        traceback.print_exc()
        global g_exit
        g_exit = True
        #dt.stop()
        mt.join()
        g_socket.shutdown(1)
        g_socket.close
        print("Exited")
        
if __name__ == "__main__":
    main()
